/*=====================================================
Critical Links
Auto Device Server

Authors:
	Rui Eduardo Gouveia Gil - r-gil@critical-links.com

Date: 2010
Version 0.1
=======================================================*/
#include "httpd/HttpUserManager.h"
#include "database/DataBase.h"
#include "httpd/SDevices.h"
#include "ACSConfig.h"

namespace acs
{

std::vector<std::string> SDevices::getHtml(std::string divID, std::string query)
{
	if(query.empty())
		return SDevices::getDeviceListHtml(divID,"");
	else
	{
		rgcpp::StringTokenizer tokenizer(query,'#');

		std::string action = tokenizer.nextToken();
		if(action.compare(SC_ACTION_NEW) == 0)
			return SDevices::getNewDeviceHtml(divID);
		else if(action.compare(SC_ACTION_SHOW) ==  0 && tokenizer.hasMoreElements())
			return SDevices::getDeviceHtml(divID,tokenizer.nextTokenInt());
		else if(action.compare(SC_ACTION_EDIT) == 0 && tokenizer.hasMoreElements())
			return SDevices::getEditDeviceHtml(divID,tokenizer.nextTokenInt());
		else if(action.compare(SC_ACTION_CONSOLE) == 0 && tokenizer.hasMoreElements())
			return SDevices::getConsoleDeviceHtml(divID,tokenizer.nextTokenInt());
		else
			return SDevices::getDeviceListHtml(divID,query);
	}
}

std::vector<std::string> SDevices::createDevice(std::string name, std::string license, int configID, std::string description)
{
	std::stringstream stream;
	std::vector<std::string> result;

	if(name.empty())
	{
		result.push_back("errorMessage");
		result.push_back("<span class=\"loginMessageError\">Invalid device name!</span>");
		result.push_back("$('deviceName').style.borderColor = '#CC0505';$('deviceLicense').style.borderColor = '#000000';");
	}
	else if(DataBase::getInstance()->existsDevice(name))
	{
		result.push_back("errorMessage");
		result.push_back("<span class=\"loginMessageError\">The device name is already in use! Please choose a different one.!</span>");
		result.push_back("$('deviceName').style.borderColor = '#CC0505';$('deviceLicense').style.borderColor = '#000000';");
	}
	else  if(license.empty())
	{
		result.push_back("errorMessage");
		result.push_back("<span class=\"loginMessageError\">Invalid device license!</span>");
		result.push_back("$('deviceName').style.borderColor = '#000000';$('deviceLicense').style.borderColor = '#CC0505';");
	}
	else
	{
		try
		{
			DataBase::getInstance()->checkDefaults();

			Device device;
			device.setName(name);
			device.setStatus(DS_PENDING_TASKS);
			device.setConfigID(configID);
			device.setLicenseID(license);
			device.setDescription(description);
			device = DataBase::getInstance()->createDevice(device);

			stream << "window.location = '/devices.html#show#" << device.getID() << "';";

			result.push_back("errorMessage");
			result.push_back("<span class=\"loginMessageError\"></span>");
			result.push_back(stream.str());
		}
		catch (rgcpp::Exception& e)
		{
			result.push_back("errorMessage");
			result.push_back("<span class=\"loginMessageError\">Server Internal Error! Please check the logs for more information.</span>");
		}
	}

	return result;
}

std::vector<std::string> SDevices::saveDevice(int deviceID, std::string name, std::string license, int configID, std::string description)
{
	std::stringstream stream;
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back("errorMessage");
		result.push_back(stream.str());
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	Device device = DataBase::getInstance()->getDevice(deviceID);

	if(name.empty())
	{
		result.push_back("errorMessage");
		result.push_back("<span class=\"loginMessageError\">Invalid device name!</span>");
		result.push_back("$('deviceName').style.borderColor = '#CC0505';$('deviceLicense').style.borderColor = '#000000';");
	}
	else if(DataBase::getInstance()->existsDevice(name) && device.getName().compare(name) != 0)
	{
		result.push_back("errorMessage");
		result.push_back("<span class=\"loginMessageError\">The device name is already in use! Please choose a different one.!</span>");
		result.push_back("$('deviceName').style.borderColor = '#CC0505';$('deviceVersion').style.borderColor = '#000000';");
	}
	else  if(license.empty())
	{
		result.push_back("errorMessage");
		result.push_back("<span class=\"loginMessageError\">Invalid device license!</span>");
		result.push_back("$('deviceName').style.borderColor = '#000000';$('deviceLicense').style.borderColor = '#CC0505';");
	}
	else
	{
		try
		{
			device.setName(name);
			if(device.getStatus() != DS_PENDING_VALIDATION && configID != device.getConfigID())
				device.setStatus(DS_PENDING_TASKS);
			device.setConfigID(configID);
			device.setLicenseID(license);
			device.setDescription(description);

			DataBase::getInstance()->updateDevice(device);

			stream << "window.location = '/devices.html#show#" << device.getID() << "';";

			result.push_back("errorMessage");
			result.push_back("<span class=\"loginMessageError\"></span>");
			result.push_back(stream.str());
		}
		catch (rgcpp::Exception& e)
		{
			result.push_back("errorMessage");
			result.push_back("<span class=\"loginMessageError\">Server Internal Error! Please check the logs for more information.</span>");
		}
	}

	return result;
}

std::vector<std::string> SDevices::validateDevice(int deviceID)
{
	std::vector<std::string> result;

	if(DataBase::getInstance()->existsDevice(deviceID))
	{
		Device device = DataBase::getInstance()->getDevice(deviceID);
		device.setStatus(DS_PENDING_TASKS);
		DataBase::getInstance()->updateDevice(device);
	}

	result.push_back("window.location.reload();");

	return result;
}


std::vector<std::string> SDevices::removeDevice(int deviceID)
{
	std::vector<std::string> result;

	DataBase::getInstance()->removeDevice(deviceID);
	result.push_back("window.location = '/devices.html';");

	return result;
}

std::vector<std::string> SDevices::clearDeviceBackupRestoreFile(std::string divID, int deviceID)
{
	std::stringstream stream;
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back(divID);
		result.push_back(stream.str());
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	Device device = DataBase::getInstance()->getDevice(deviceID);
	device.setConfigFileName("");
	DataBase::getInstance()->updateDevice(device);

	stream << "			<span class=\"head2\">Backup/Restore File</span><br/><br/>";
	stream << "			<form method=\"POST\" enctype=\"multipart/form-data\" action='/FileUpload?type=2&id=" << deviceID << "'>";
	stream << "				<span class=\"head3\">Upload new file:&nbsp;</span>";
	stream << "				<input id=\"upfile\" name=\"upfile\" type=\"file\" class=\"text\" />&nbsp;&nbsp;<input type=\"submit\" value=\"Upload\" style=\"width:60px;\"/>";
	stream << "			</form>";

	stream << "			<br/>";

	result.push_back(divID);
	result.push_back(stream.str());

	return result;
}

std::vector<std::string> SDevices::addDeviceCommand(std::string divID, int deviceID, std::string command)
{
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back(divID);
		result.push_back("");
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	boost::trim(command);

	if(!command.empty())
	{
		rgcpp::StringTokenizer tokenizer(command,' ');

		std::string cmd = tokenizer.nextToken();
		std::vector<std::string> args;
		while(tokenizer.hasMoreElements())
			args.push_back(tokenizer.nextToken());

		DataBase::getInstance()->addDeviceCommand(Command(deviceID,cmd,args));

		Device device = DataBase::getInstance()->getDevice(deviceID);
		if(device.getStatus() != DS_PENDING_VALIDATION)
			device.setStatus(DS_PENDING_TASKS);
		DataBase::getInstance()->updateDevice(device);
	}

	result.push_back(divID);
	result.push_back(SDevices::getDeviceCommandHtml(deviceID));
}

std::vector<std::string> SDevices::switchDeviceCommand(std::string divID, int deviceID, int index1, int index2)
{
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back(divID);
		result.push_back("");
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	DataBase::getInstance()->switchDeviceCommandIndex(deviceID,index1,index2);
	Device device = DataBase::getInstance()->getDevice(deviceID);
	if(device.getStatus() != DS_PENDING_VALIDATION)
		device.setStatus(DS_PENDING_TASKS);
	DataBase::getInstance()->updateDevice(device);

	result.push_back(divID);
	result.push_back(SDevices::getDeviceCommandHtml(deviceID));
}

std::vector<std::string> SDevices::removeDeviceCommand(std::string divID, int deviceID, int index)
{
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back(divID);
		result.push_back("");
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	DataBase::getInstance()->removeDeviceCommand(deviceID,index);
	Device device = DataBase::getInstance()->getDevice(deviceID);
	if(device.getStatus() != DS_PENDING_VALIDATION)
		device.setStatus(DS_PENDING_TASKS);
	DataBase::getInstance()->updateDevice(device);

	result.push_back(divID);
	result.push_back(SDevices::getDeviceCommandHtml(deviceID));
}


std::vector<std::string> SDevices::generateConfiguration(int deviceID, std::string name)
{
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	if(DataBase::getInstance()->existsConfiguration(name))
	{
		result.push_back("alert('Unable to create configuration template. Already exists a configuration with the same name.');");
		return result;
	}
	else
	{
		Device device= DataBase::getInstance()->getDevice(deviceID);

		Configuration configuration;
		configuration.setName(name);
		configuration = DataBase::getInstance()->createConfiguration(configuration);

		std::vector<Command> commands = device.getCommands();
		for(std::vector<Command>::iterator itr=commands.begin(); itr!=commands.end(); itr++)
		{
			itr->setID(configuration.getID());
			DataBase::getInstance()->addConfigurationCommand(*itr);
		}

		if(!device.getConfigFileName().empty())
		{
			std::string srcFile = ACSConfig::getDataDirectory()+std::string("Device_BackupRestore_")+rgcpp::ToString(device.getID());
			std::string destFile = ACSConfig::getDataDirectory()+std::string("Configuration_BackupRestore_")+rgcpp::ToString(configuration.getID());

			boost::filesystem::copy_file(srcFile,destFile);

			configuration.setConfigFileName(device.getConfigFileName());
			DataBase::getInstance()->updateConfiguration(configuration);
		}

		result.push_back("alert('Configuration template has been succesfully created.');");
		return result;
	}
}

std::vector<std::string> SDevices::getDevices(std::string query)
{
	std::vector<std::string> result;

	result.push_back("devicesList");
	result.push_back(SDevices::getDevicesHtml(query));

	return result;
}

std::vector<std::string> SDevices::getLogs(int deviceID, int offset, int limit)
{
	std::vector<std::string> result;

	result.push_back("deviceLog");
	result.push_back(SDevices::getLogsHtml(deviceID,offset,limit));

	return result;
}

std::vector<std::string> SDevices::getDeviceListHtml(std::string divID, std::string text)
{
	std::stringstream stream;
	std::vector<std::string> result;

	stream << "<table width=\"1024\">";
	stream << "	<tr><td>";

	stream << "		<br/>";

	stream << "		<div style=\"overflow: hidden; margin-left: 10px;\">";
	stream << "			<span class=\"head1\">Devices :: List</span><br/>";
	stream << "		</div>";
	stream << "		<div style=\"overflow: hidden;\">";
	stream << "			<a href=\"javascript: $('loading').style.visibility='visible'; window.location = '/devices.html#'+$('searchInputText').value;\" class=\"searchImage\" style=\"float:right;\"></a>";
	stream << "			<input id=\"searchInputText\" type=\"text\" class=\"searchInput\" style=\"float:right;\" value=\"" << text << "\" onkeypress=\"javascript: if(checkEnter(event)){$('loading').style.visibility='visible'; window.location = '/devices.html#'+$('searchInputText').value;}\"/>";
	stream << "			<span style=\"float:left; margin-left: 20px; margin-top: 5px;\"><a href=\"/devices.html#new\" class=\"textLink\">[new device]</a></span>";
	stream << "		</div>";

	stream << "		<hr/>";


	stream << "		<div id=\"devicesList\"style=\"overflow: hidden; margin-left: 20px;\">";
	stream << 			SDevices::getDevicesHtml(text);
	stream << "		</div>";

	stream << "		<hr/>";

	stream << "	</td></tr>";
	stream << "</table>";

	result.push_back(divID);
	result.push_back(stream.str());

	return result;
}

std::vector<std::string> SDevices::getNewDeviceHtml(std::string divID)
{
	std::stringstream stream;
	std::vector<std::string> result;

	stream << "<table width=\"1024\">";
	stream << "	<tr><td>";

	stream << "		<br/>";

	stream << "		<div style=\"overflow: hidden; margin-left: 10px;\">";
	stream << "			<span class=\"head1\">Devices :: New</span><br/>";
	stream << "		</div>";

	stream << "		<hr/>";

	stream << "<table style=\"margin-left: 20px;\">";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td valign=\"top\">";
	stream << "			<span class=\"head3\">Name:&nbsp;&nbsp;&nbsp;</span><br/>";
	stream << "		</td>";
	stream << "		<td>";
	stream << "			<input class=\"inputText\" type=\"text\" id=\"deviceName\" name=\"deviceName\" value=\"\" /><br/>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td valign=\"top\">";
	stream << "			<span class=\"head3\">License:&nbsp;&nbsp;&nbsp;</span><br/>";
	stream << "		</td>";
	stream << "		<td>";
	stream << "			<input class=\"inputText\" type=\"text\" id=\"deviceLicense\" name=\"deviceLicense\" value=\"\" /><br/>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td valign=\"top\">";
	stream << "			<span class=\"head3\">Configuration:&nbsp;&nbsp;&nbsp;</span><br/>";
	stream << "		</td>";
	stream << "		<td>";
	stream << "			<select class=\"inputText\" id=\"deviceConfig\" name=\"deviceConfig\">";
	stream << "				<option value=\"0\" selected=\"selected\">none</option>";
	std::vector<Configuration> configurations = DataBase::getInstance()->listConfigurations("");
	for(std::vector<Configuration>::iterator itr=configurations.begin(); itr!=configurations.end(); itr++)
	{
		stream << "				<option value=\"" << itr->getID() << "\">" << itr->getName() << "</option>";
	}
	stream << "			</select><br/>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td valign=\"top\">";
	stream << "			<span class=\"head3\">Description:&nbsp;&nbsp;&nbsp;</span><br/>";
	stream << "		</td>";
	stream << "		<td>";
	stream << "			<textarea class=\"inputTextArea\" type=\"text\" id=\"deviceDescription\" name=\"deviceDescription\" rows=\"4\" ></textarea><br/>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td></td>";
	stream << "		<td align=\"center\">";
	stream << "			<input type=\"button\" value=\"Create\" style=\"width:60px;\" onclick=\"javascript: $('loading').style.visibility='visible'; SDevices.createDevice($('deviceName').value,$('deviceLicense').value,$('deviceConfig').value,$('deviceDescription').value,redrawLayer);\" />&nbsp;&nbsp;|&nbsp;&nbsp;<a href=\"/devices.html\" class=\"cancelLink\">Cancel<a>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "</table>";
	stream << "	<br/>";
	stream << "	<div id=\"errorMessage\"></div></";
	stream << "	<br/>";
	stream << "	</td></tr>";
	stream << "</table>";

	result.push_back(divID);
	result.push_back(stream.str());

	return result;
}

std::vector<std::string> SDevices::getEditDeviceHtml(std::string divID, int deviceID)
{
	std::stringstream stream;
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back(divID);
		result.push_back(stream.str());
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	Device device = DataBase::getInstance()->getDevice(deviceID);

	stream << "<table width=\"1024\">";
	stream << "	<tr><td>";

	stream << "		<br/>";

	stream << "		<div style=\"overflow: hidden; margin-left: 10px;\">";
	stream << "			<span class=\"head1\">Devices :: " << device.getName() << " :: Edit</span><br/>";
	stream << "		</div>";

	stream << "		<hr/>";

	stream << "<table style=\"margin-left: 20px;\">";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td valign=\"top\">";
	stream << "			<span class=\"head3\">Name:&nbsp;&nbsp;&nbsp;</span><br/>";
	stream << "		</td>";
	stream << "		<td>";
	stream << "			<input class=\"inputText\" type=\"text\" id=\"deviceName\" name=\"deviceName\" value=\"" << device.getName() << "\" /><br/>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td valign=\"top\">";
	stream << "			<span class=\"head3\">License:&nbsp;&nbsp;&nbsp;</span><br/>";
	stream << "		</td>";
	stream << "		<td>";
	stream << "			<input class=\"inputText\" type=\"text\" id=\"deviceLicense\" name=\"deviceLicense\" value=\"" << device.getLicenseID() << "\" /><br/>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td valign=\"top\">";
	stream << "			<span class=\"head3\">Configuration:&nbsp;&nbsp;&nbsp;</span><br/>";
	stream << "		</td>";
	stream << "		<td>";
	stream << "			<select class=\"inputText\" id=\"deviceConfig\" name=\"deviceConfig\">";
	if(device.getConfigID() == 0)
		stream << "			<option value=\"0\" selected=\"selected\">none</option>";
	else
		stream << "			<option value=\"0\" selected=\"selected\">none</option>";
	std::vector<Configuration> configurations = DataBase::getInstance()->listConfigurations("");
	for(std::vector<Configuration>::iterator itr=configurations.begin(); itr!=configurations.end(); itr++)
	{
		if(itr->getID() == device.getConfigID())
			stream << "		<option value=\"" << itr->getID() << "\" selected=\"selected\">" << itr->getName() << "</option>";
		else
			stream << "		<option value=\"" << itr->getID() << "\">" << itr->getName() << "</option>";
	}
	stream << "			</select><br/>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td valign=\"top\">";
	stream << "			<span class=\"head3\">Description:&nbsp;&nbsp;&nbsp;</span><br/>";
	stream << "		</td>";
	stream << "		<td>";
	stream << "			<textarea class=\"inputTextArea\" type=\"text\" id=\"deviceDescription\" name=\"deviceDescription\" rows=\"4\" >" << device.getDescription() << "</textarea><br/>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "	<tr style=\"height: 30px\">";
	stream << "		<td></td>";
	stream << "		<td align=\"center\">";
	stream << "			<input type=\"button\" value=\"Save\" style=\"width:60px;\" onclick=\"javascript: $('loading').style.visibility='visible'; SDevices.saveDevice(" << device.getID() << ",$('deviceName').value,$('deviceLicense').value,$('deviceConfig').value,$('deviceDescription').value,redrawLayer);\" />&nbsp;&nbsp;|&nbsp;&nbsp;<a href=\"/devices.html#show#" << device.getID() << "\" class=\"cancelLink\">Cancel<a>";
	stream << "		</td>";
	stream << "	</tr>";
	stream << "</table>";
	stream << "	<br/>";
	stream << "	<div id=\"errorMessage\"></div></";
	stream << "	<br/>";
	stream << "	</td></tr>";
	stream << "</table>";

	result.push_back(divID);
	result.push_back(stream.str());

	return result;
}

std::vector<std::string> SDevices::getConsoleDeviceHtml(std::string divID, int deviceID)
{
	std::stringstream stream;
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back(divID);
		result.push_back(stream.str());
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	Device device = DataBase::getInstance()->getDevice(deviceID);

	stream << "<table width=\"1024\">";
	stream << "	<tr><td>";

	stream << "		<br/>";

	stream << "		<div style=\"overflow: hidden; margin-left: 10px;\">";
	stream << "			<span class=\"head1\">Devices :: " << device.getName() << " :: Console</span><br/>";
	stream << "		</div>";

	stream << "		<hr/>";

	stream << "	</td></tr>";
	stream << "</table>";

	result.push_back(divID);
	result.push_back(stream.str());

	return result;
}

std::vector<std::string> SDevices::getDeviceHtml(std::string divID, int deviceID)
{
	std::stringstream stream;
	std::vector<std::string> result;

	if(!DataBase::getInstance()->existsDevice(deviceID))
	{
		result.push_back(divID);
		result.push_back(stream.str());
		result.push_back("window.location = '/devices.html';");
		return result;
	}

	Device device = DataBase::getInstance()->getDevice(deviceID);

	stream << "<table width=\"1024\">";
	stream << "	<tr><td>";

	stream << "		<br/>";

	stream << "		<div style=\"overflow: hidden; margin-left: 10px;\">";
	stream << "			<span class=\"head1\">Devices :: " << device.getName() << "</span><br/>";
	stream << "			<span style=\"float:left; margin-left: 10px; margin-top: 5px;\"><a href=\"/devices.html#edit#" << device.getID() << "\" class=\"textLink\">[edit]</a></span>&nbsp;&nbsp;";
	stream << "			<span style=\"float:left; margin-left: 10px; margin-top: 5px;\"><a href=\"javascript: if(confirm('Are you sure you want to delete this device?')){$('loading').style.visibility='visible'; SDevices.removeDevice(" << deviceID << ",executeScriptLoading);}\" class=\"textLink\">[delete]</a></span>&nbsp;&nbsp;";
//	stream << "			<span style=\"float:left; margin-left: 10px; margin-top: 5px;\"><a href=\"/devices.html#console#" << device.getID() << "\" class=\"textLink\">[console]</a></span>&nbsp;&nbsp;";
	stream << "		</div>";

	stream << "		<hr/>";

	stream << "		<div style=\"margin-left: 20px;\">";
	stream << "			<span class=\"head3\">Name:&nbsp;</span><span class=\"text\">" << device.getName() << "</span><br/>";
	stream << "			<span class=\"head3\">Status:&nbsp;</span><span class=\"text\">" << device.getStatusStr() << "</span><br/>";
	if(device.getConfigID() == 0)
		stream << "			<span class=\"head3\">Configuration:&nbsp;</span><span class=\"text\">none</span><br/>";
	else
		stream << "			<span class=\"head3\">Configuration:&nbsp;</span><a href=\"/configurations.html#show#" << device.getConfigID() << "\" class=\"textLink\">" << DataBase::getInstance()->getConfiguration(device.getConfigID()).getName() << "</a><br/>";
	if(device.getIp().empty())
		stream << "			<span class=\"head3\">Ip:&nbsp;</span><span class=\"text\">not online</span><br/>";
	else
		stream << "			<span class=\"head3\">Ip:&nbsp;</span><span class=\"text\">" << device.getIp() << "</span><br/>";
	stream << "			<span class=\"head3\">License:&nbsp;</span><span class=\"text\">" << device.getLicenseID() << "</span><br/>";
	stream << "			<span class=\"head3\">Created on:&nbsp;</span><span class=\"text\">" << rgcpp::ToString(device.getCreation(),"%Y-%m-%d %X") << "</span><br/>";
	stream << "			<span class=\"head3\">Last update on:&nbsp;</span><span class=\"text\">" << rgcpp::ToString(device.getUpdated(),"%Y-%m-%d %X") << "</span><br/>";
	if(device.getContacted() == 0)
		stream << "		<span class=\"head3\">Last contact on:&nbsp;</span><span class=\"text\">never</span><br/>";
	else
		stream << "		<span class=\"head3\">Last contact on:&nbsp;</span><span class=\"text\">" << rgcpp::ToString(device.getContacted(),"%Y-%m-%d %X") << "</span><br/>";
	stream << "			<span class=\"head3\">Description:&nbsp;</span><span class=\"text\">" << device.getDescription() << "</span><br/>";

	if(device.getStatus() == DS_PENDING_VALIDATION)
		stream << "		<br/><input type=\"button\" value=\"Validate Device\" style=\"width:120px;\" onclick=\"javascript: $('loading').style.visibility='visible'; SDevices.validateDevice(" << device.getID() << ",executeScriptLoading);\"/><br/>";

	stream << "			<br/>";
	stream << "		</div>";

	stream << "		<hr/>";

	stream << "		<div id=\"systemInformation\" style=\"margin-left: 20px;\">";
	stream << "			<span class=\"head2\">System Information</span><br/><br/>";
	stream << "			<span class=\"head3\">Customer Name:&nbsp;</span><span class=\"text\">" << device.getCustomerName() << "</span><br/>";
	stream << "			<span class=\"head3\">Max Users:&nbsp;</span><span class=\"text\">" << device.getMaxUsers() << "</span><br/>";
	stream << "			<span class=\"head3\">Release:&nbsp;</span><span class=\"text\">" << device.getRelease() << "</span><br/>";
	stream << "			<span class=\"head3\">Build:&nbsp;</span><span class=\"text\">" << device.getBuild() << "</span><br/>";
	stream << "			<span class=\"head3\">PEPs Version:&nbsp;</span><span class=\"text\">" << device.getPepsVersion() << "</span><br/>";
	stream << "			<span class=\"head3\">GUI Version:&nbsp;</span><span class=\"text\">" << device.getGuiVersion() << "</span><br/>";
	stream << "			<span class=\"head3\">Up time:&nbsp;</span><span class=\"text\">" << device.getUpTime() << "</span><br/>";
	stream << "			<span class=\"head3\">System Load:&nbsp;</span><span class=\"text\">" << device.getSystemLoad() << "</span><br/>";
	stream << "			<span class=\"head3\">Installed Memory:&nbsp;</span><span class=\"text\">" << device.getInstalledMemory() << "</span><br/>";
	stream << "			<span class=\"head3\">Free Memory:&nbsp;</span><span class=\"text\">" << device.getFreeMemory() << "</span><br/>";
	stream << "			<span class=\"head3\">Swap Used:&nbsp;</span><span class=\"text\">" << device.getSwapUsed() << "</span><br/>";
	stream << "			<span class=\"head3\">Partition /:&nbsp;</span><span class=\"text\">" << device.getPartitionRoot() << "</span><br/>";
	stream << "			<span class=\"head3\">Partition /var:&nbsp;</span><span class=\"text\">" << device.getPartitionVar() << "</span><br/>";
	stream << "			<span class=\"head3\">Partition /home:&nbsp;</span><span class=\"text\">" << device.getPartitionHome() << "</span><br/>";
	stream << "			<span class=\"head3\">Hardware Description:&nbsp;</span><span class=\"text\">" << device.getHardwareDescription() << "</span><br/><br/>";
	stream << "		</div>";

//	stream << "		<div id=\"backupRestoreFile\" style=\"margin-left: 10px;\">";
//	stream << "			<span class=\"head2\">Backup/Restore File</span><br/><br/>";
//	std::string fileName = device.getConfigFileName();
//	std::string destFile = ACSConfig::getDataDirectory()+std::string("Device_BackupRestore_")+rgcpp::ToString(deviceID);
//	if(!fileName.empty() && boost::filesystem::exists(destFile))
//	{
//		stream << "			<span class=\"head3\">Name:&nbsp;</span><span class=\"text\">" << fileName << "</span><br/>";
//		stream << "			<span class=\"head3\">Size:&nbsp;</span><span class=\"text\">" << rgcpp::ToStringHumanReadable(boost::filesystem::file_size(destFile)) << "</span><br/>";
//		stream << "			<span class=\"head3\">Date:&nbsp;</span><span class=\"text\">" << rgcpp::ToString(boost::filesystem::last_write_time(destFile),"%Y-%m-%d %X") << "</span><br/>";
//		stream << "			<input type=\"button\" value=\"Clear File\" style=\"width:120px;\" onclick=\"javascript: if(confirm('Are you sure you want to clear backup/restore file?')){$('loading').style.visibility='visible'; SDevices.clearDeviceBackupRestoreFile('backupRestoreFile'," << device.getID() << ",redrawLayer);}\" />";
//		stream << "			<br/><br/>";
//	}
//	stream << "			<form method=\"POST\" enctype=\"multipart/form-data\" action='/FileUpload?type=2&id=" << deviceID << "'>";
//	stream << "				<span class=\"head3\">Upload new file:&nbsp;</span>";
//	stream << "				<input id=\"upfile\" name=\"upfile\" type=\"file\" class=\"text\" />&nbsp;&nbsp;<input type=\"submit\" value=\"Upload\" style=\"width:60px;\"/>";
//	stream << "			</form>";
//
//	stream << "			<br/>";
//	stream << "		</div>";
//
	if(HttpUserManager::getInstance()->getCurrentUser().getType() == ACS_USER_ADMIN)
	{
		stream << "		<hr/>";

		stream << "		<div id=\"commandList\" style=\"margin-left: 20px;\">";
		stream << 			SDevices::getDeviceCommandHtml(device.getID());
		stream << "		</div>";
	}

	stream << "		<hr/>";

	stream << "		<div id=\"deviceLog\" style=\"margin-left: 20px;\">";
	stream << 			SDevices::getLogsHtml(deviceID, 0, SC_DEVICE_LOG_LIMIT);
	stream << "		</div>";

	stream << "	</td></tr>";
	stream << "</table>";

	result.push_back(divID);
	result.push_back(stream.str());

	return result;
}

std::string SDevices::getDeviceCommandHtml(int deviceID)
{
	std::stringstream stream;

	stream << "			<span class=\"head2\">Command List</span><br/><br/>";

	std::vector<std::string> arguments;
	std::vector<Command> commands = DataBase::getInstance()->getDeviceCommands(deviceID);
	for(std::vector<Command>::iterator itr=commands.begin(); itr!=commands.end(); itr++)
	{
		stream << "		<a href=\"javascript: $('loading').style.visibility='visible'; SDevices.removeDeviceCommand('commandList'," << deviceID << "," << itr->getIndex() << ",redrawLayer);\" class=\"textLink\">[x]</a>&nbsp;";
		if(itr->getIndex() == 0)
			stream << "		<span class=\"disableTextLink\">[up]</span>&nbsp;";
		else
			stream << "		<a href=\"javascript: $('loading').style.visibility='visible'; SDevices.switchDeviceCommand('commandList'," << deviceID << "," << itr->getIndex() << "," << itr->getIndex() - 1 << ",redrawLayer);\" class=\"textLink\">[up]</a>&nbsp;";
		if(itr->getIndex() == commands.size()-1)
			stream << "		<span class=\"disableTextLink\">[down]</span>&nbsp;";
		else
			stream << "		<a href=\"javascript: $('loading').style.visibility='visible'; SDevices.switchDeviceCommand('commandList'," << deviceID << "," << itr->getIndex() << "," << itr->getIndex() + 1 << ",redrawLayer);\" class=\"textLink\">[down]</a>&nbsp;";
		stream << "		&nbsp;<span class=\"text\" style=\"font-weight: bold;\" >" << itr->getCommand() << "</span>&nbsp;";
		arguments = itr->getArguments();
		for(std::vector<std::string>::iterator itr2=arguments.begin(); itr2!=arguments.end(); itr2++)
			stream << "		<span class=\"text\">" << *itr2 << "</span>&nbsp;";
		stream << "		<br/>";
	}
	stream << "		<br/>";

	stream << "			<input class=\"inputText\" type=\"text\" style=\"width:435px; height:20px; font-size: 12px;\" id=\"commandInput\" name=\"commandInput\" onkeypress=\"javascript: if(checkEnter(event)){$('loading').style.visibility='visible';  SDevices.addDeviceCommand('commandList'," << deviceID << ",$('commandInput').value,redrawLayer);}\"/>&nbsp;&nbsp;";
	stream << "			<input type=\"button\" value=\"Add Command\" style=\"width:120px;\" onclick=\"javascript: $('loading').style.visibility='visible'; SDevices.addDeviceCommand('commandList'," << deviceID << ",$('commandInput').value,redrawLayer);\" />";

	return stream.str();
}

std::string SDevices::getDevicesHtml(std::string text)
{
	std::stringstream stream;

	std::vector<Device> devices = DataBase::getInstance()->listDevices(text);
	if(devices.empty())
	{
		if(text.empty())
			stream << "<span class=\"text\">No results found...</span>";
		else
			stream << "<span class=\"text\">No results found for: " << text <<"</span>";
	}
	else
	{
		stream << "		<table width=\"1004\">";
		stream << "		<tr class=\"tableRowHeader\">";
		stream << "			<td>Name</td><td>Release</td><td>Ip</td><td>Configuration</td><td>Last Contact On</td><td>License</td><td>Customer</td>";
		stream << "		</tr>";
		for(std::vector<Device>::iterator itr=devices.begin(); itr!=devices.end(); itr++)
		{
			stream << "		<tr cellpadding=\"0\" cellspacing=\"0\" class=\"tableRow\" onmouseover=\"javascript: document.body.style.cursor = 'pointer';\" onmouseout=\"javascript: document.body.style.cursor = 'default';\" onclick=\"javascript: window.location = '/devices.html#show#" << itr->getID() << "'; document.body.style.cursor = 'default';\">";
			if(itr->getConfigID() == 0)
				stream << "			<td>" << itr->getStatusIcon() << "&nbsp;&nbsp;" << itr->getName() << "</td><td>" << itr->getRelease() << "</td><td>" << (itr->getIp().empty() ? "not online" : itr->getIp()) << "</td><td>none</td><td>" << (itr->getContacted() == 0 ? "never" : rgcpp::ToString(itr->getContacted(),"%Y-%m-%d %X")) << "</td><td>" << itr->getLicenseID() << "</td><td>" << itr->getCustomerName() << "</td>";
			else
				stream << "			<td>" << itr->getStatusIcon() << "&nbsp;&nbsp;" << itr->getName() << "</td><td>" << itr->getRelease() << "</td><td>" << (itr->getIp().empty() ? "not online" : itr->getIp()) << "</td><td>" << DataBase::getInstance()->getConfiguration(itr->getConfigID()).getName() << "</td><td>" << (itr->getContacted() == 0 ? "never" : rgcpp::ToString(itr->getContacted(),"%Y-%m-%d %X")) << "</td><td>" << itr->getLicenseID() << "</td><td>" << itr->getCustomerName() << "</td>";
			stream << "		</tr>";
		}
		stream << "		</table>";
	}

	return stream.str();
}

std::string SDevices::getLogsHtml(int deviceID, int offset, int limit)
{
	std::stringstream stream;
	stream << "			<span class=\"head2\">Device Access Log</span><br/><br/>";

	unsigned int count = DataBase::getInstance()->getLastLogsCount(deviceID);
	std::vector<Log> logs = DataBase::getInstance()->getLastLogs(deviceID,ACS_LL_NOTICE,offset,limit);

	if(logs.empty())
	{
		stream << "	<div style=\"overflow: hidden;\">";
			stream << "<span class=\"text\">No logs available...</span>";
		stream << "	</div>";
	}
	else
	{
		stream << "	<div style=\"overflow: hidden;\">";
		stream << "		<table width=\"1004\">";
		stream << "		<tr class=\"tableRowHeader\">";
		stream << "			<td>Log</td<td>Time</td><td>IP</td><td>Release</td><td>Command</td><td>Result</td><td>Message</td>";
		stream << "		</tr>";
		for(std::vector<Log>::iterator itr=logs.begin(); itr!=logs.end(); itr++)
		{
			stream << "		<tr cellpadding=\"0\" cellspacing=\"0\" class=\"tableSimpleRow\" >";
			switch(itr->getLevel())
			{
				case ACS_LL_DEBUG:
				{
					stream << "			<td style=\"width: 80px;\">Trace</td>";
				}break;
				case ACS_LL_NOTICE:
				{
					stream << "			<td style=\"width: 80px;\">Information</td>";
				}break;
				case ACS_LL_ERROR:
				{
					stream << "			<td style=\"width: 80px;\">Error</td>";
				}break;
				default:
				{
					stream << "			<td style=\"width: 80px;\">Warning</td>";
				}break;
			}
			stream << "			<td style=\"width: 150px;\">" << rgcpp::ToString(itr->getDate(),"%Y-%m-%d %X") << "</td><td style=\"width: 110px;\">" << itr->getIp() << "</td><td style=\"width: 120px;\">" << itr->getRelease() << "</td><td>" << itr->getCommand() << "</td><td style=\"width: 100px;\">" << itr->getResult() << "</td><td>" << itr->getMessage() << "</td>";
			stream << "		</tr>";
		}
		stream << "		</table>";
		stream << "	</div>";

	}

	return stream.str();
}


}
